package com.rivues.util.datasource;

import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.rivu.tools.ParamTools;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import com.alibaba.druid.stat.DruidDataSourceStatManager;
import com.rivues.core.RivuDataContext;
import com.rivues.module.platform.web.model.Database;
import com.rivues.util.RivuTools;
import com.rivues.util.service.cache.CacheHelper;

/**
 * 连接池相关系统监测
 * @author admin
 *
 */
public class DataSourceTools {
	/**
     * 获取当前连接池信息
     * @param dsName
     * @return
     */
    public static DruidDataSource getDataSource(String dsName){
    	DruidDataSource ds = null ;
    	for(DruidDataSource datasource : DruidDataSourceStatManager.getDruidDataSourceInstances()){
    		if(dsName.equals(datasource.getName())){
    			ds = datasource ;
    			break;
    		}
    	}
    	return ds ;
    }
    
    /**
     * 获取当前连接池信息
     * @param dsName
     * @return
     */
    public static Map<String,Object> getDataSourceStat(String dsName){
    	DruidDataSource ds = getDataSource(dsName) ;
    	return ds!=null ? ds.getStatData() : new HashMap<String , Object>() ;
    }
    
    
    /**
     * 创建数据库连接池
     * @param database
     * @return
     * @throws SQLException
     * @throws NoSuchAlgorithmException 
     */
    public static DruidDataSource createDataSource(Database database) throws SQLException, NoSuchAlgorithmException{
    	
    	DruidDataSource dataSource = null ;
    	String dsName = database.getId() ;
    	if(RivuDataContext.R3_SYSTEM.equalsIgnoreCase(database.getName())){
    		dsName = (RivuDataContext.R3_SYSTEM) ;
    	}
    	
    	if((dataSource = getDataSource(dsName))==null){
    		if(RivuDataContext.ConnectionTypeEnum.JNDI.toString().equals(database.getConnctiontype())){	//判断下是否是 JNDI，如果是JNDI，就直接用 JndiDataSource 来创建， new JndiDataSource
    			dataSource = new JndiDataSource(database);
    			dataSource.setName(dsName);
    			DruidDataSourceStatManager.addDataSource(dataSource , dsName) ;
    		}else{
		    	dataSource = new DruidDataSource();
		    	dataSource.setName(dsName) ;
		    	dataSource.setUrl(database.getDatabaseurl()); 
		    	dataSource.setDriverClassName(database.getDriverclazz()); 
		    	dataSource.setUsername(database.getAccount()); 
		    	dataSource.setPassword(RivuTools.decryption(database.getPassword())); 
		    	
		    	dataSource.setInitialSize(Integer.parseInt(RivuTools.getValue("InitialSize", database.getOrgi(), "5"))); 
		    	dataSource.setMinIdle(Integer.parseInt(RivuTools.getValue("MinIdle", database.getOrgi(), "5"))); 
		    	dataSource.setMaxActive(Integer.parseInt(RivuTools.getValue("MaxActive", database.getOrgi(), "500"))); 
		    	dataSource.setMaxWait(Integer.parseInt(RivuTools.getValue("MaxWait", database.getOrgi(), "60000"))) ;
		    	dataSource.setMinEvictableIdleTimeMillis(Integer.parseInt(RivuTools.getValue("MinEvictableIdleTimeMillis", database.getOrgi(), "300000"))) ;
		    	dataSource.setRemoveAbandoned(Boolean.parseBoolean(RivuTools.getValue("RemoveAbandoned", database.getOrgi(), "false")));//超过时间限制是否回收
		    	dataSource.setRemoveAbandonedTimeout(Integer.parseInt(RivuTools.getValue("RemoveAbandonedTimeout", database.getOrgi(), "180")));//超过时间限制多长
		    	dataSource.setTimeBetweenEvictionRunsMillis(Integer.parseInt(RivuTools.getValue("TimeBetweenEvictionRunsMillis", database.getOrgi(), "60000")));//配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒 
		    	dataSource.setConnectionProperties(RivuTools.getValue("ConnectionProperties", database.getOrgi(), "druid.stat.mergeSql=true")) ;
		    	dataSource.setTestWhileIdle(Boolean.parseBoolean(RivuTools.getValue("TestWhileIdle", database.getOrgi(), "true")));
		    	dataSource.setTestOnBorrow(Boolean.parseBoolean(RivuTools.getValue("TestOnBorrow", database.getOrgi(), "false"))) ;
		    	dataSource.setTestOnReturn(Boolean.parseBoolean(RivuTools.getValue("TestOnReturn", database.getOrgi(), "false"))) ;
		    	dataSource.setPoolPreparedStatements(Boolean.parseBoolean(RivuTools.getValue("PoolPreparedStatements", database.getOrgi(), "true"))) ;
		    	dataSource.setMaxPoolPreparedStatementPerConnectionSize(Integer.parseInt(RivuTools.getValue("MaxPoolPreparedStatementPerConnectionSize", database.getOrgi(), "20"))) ;
		    	dataSource.setValidationQuery(RivuTools.getValue("ValidationQuery."+database.getDatabasetype(), database.getOrgi(), "SELECT 1")) ;
		    	dataSource.setTimeBetweenLogStatsMillis(3600000) ;
		    	
		    	//sql中有中文会报错，所以在此注释掉  stat监控统计用   wall防sql注入  log4j日志
		    	//dataSource.setFilters("stat,wall");
		    	//dataSource.setFilters("stat");
		    	Connection connection = dataSource.getConnection();
		    	Statement statement = connection.createStatement();
		    	ResultSet result = statement.executeQuery(RivuTools.getValue("ValidationQuery", database.getOrgi(), "SELECT 1")) ;
		    	String schema = null ; 
		    	Properties properties = ParamTools.getProperties(ParamTools.getProperties(null , database.getConnectparam() , database.getAccount()),database.getConnectparam(),database.getAccount()) ;
		    	if(properties!=null && properties.get("schema")!=null && schema==null){
					schema = properties.get("upcase")!=null?((String)properties.get("schema")).toUpperCase():(String)properties.get("schema") ;
				}
				if(schema!=null && schema.equals("hive")){
					statement = connection.createStatement() ;
					if(properties.get("database")!=null){
						statement.execute("USE "+properties.get("database")) ;
					}
					statement.close() ;
				}
		    	
		    	result.close();
		    	statement.close();
		    	connection.close();
    		}
    	}
		return dataSource;
    	
    }
    /**
     * 关闭数据库连接池
     * @param dsName
     */
    public static void closeDataSource(String dsName){
    	getDataSource(dsName).close() ;
    }

}
